/***
 * Copyright (c) 2021-2031 murenchao
 * fig is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *       http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package cool.taomu.software.fig.scriptutils

import java.io.Serializable
import org.apache.commons.io.IOUtils
import org.apache.commons.lang3.SerializationUtils
import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import org.mozilla.javascript.ScriptableObject
import org.slf4j.LoggerFactory

class JsRhinoScript implements IFigScript, AutoCloseable {
    val static LOG = LoggerFactory.getLogger(JsRhinoScript)
    val cx = Context.enter();
    val scope = cx.initStandardObjects();

    new(String path) {
        LOG.info(String.format("加载脚本:%s", path))
        var input = Thread.currentThread.contextClassLoader.getResourceAsStream(
            "cool/taomu/software/fig/scriptutils/json2.min.js")
        ScriptableObject.putProperty(scope, "out", Context.javaToJS(System.out, scope))
        cx.evaluateString(scope, IOUtils.toString(input, "UTF-8"), null, 1, null);
        var script = Thread.currentThread.contextClassLoader.getResourceAsStream(path)
        cx.evaluateString(scope, IOUtils.toString(script, "UTF-8"), null, 2, null);
    }

    override <K, T extends Serializable> K invoke(String name, T value) {
        var func = scope.get(name)
        if (func instanceof Function) {
            var jfunc = func;
            var T inValue = SerializationUtils.clone(value)
            var result = jfunc.call(cx, scope, scope, #[Context.javaToJS(inValue, scope)])
            return result !== null ? Context.jsToJava(result, Object) as K
        } else {
            LOG.info("unkown method : " + name);
            return null;
        }
    }

    override close() throws Exception {
        Context.exit()
    }

}
